﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MindFactorial.Dynamic
{
    public class DynamicFunctionContext<RETVAL>
    {
        object _internal;
        Func<RETVAL> _function;
        string _function_name;

        public DynamicFunctionContext(object obj, string function_name)
        {
            _internal = obj;
            this._function_name = function_name;
        }

        public bool IsDefined
        {
            get
            {
                if (_function != null)
                    return true;
                else
                {
                    object prototype = _internal.GetPrototype();
                    if (prototype != null)
                        return prototype.function<RETVAL>(_function_name).IsDefined;
                    else
                        return false;
                }
            }
        }

        public Func<RETVAL> define
        {
            set
            {
                _function = value;
            }
        }

        public Func<RETVAL> call
        {
            get
            {
                if (_function != null)
                    return _function;
                else
                {
                    object prototype = _internal.GetPrototype();
                    if (prototype != null)
                        return prototype.function<RETVAL>(_function_name).call ;
                }

                throw new MissingMethodException("The specified function has not been defined for this instance");
            }
        }

    }

    public class DynamicFunctionContext<PARAM1,RETVAL>
    {
        object _internal;
        Func<PARAM1,RETVAL> _function;
        string _function_name;

        public DynamicFunctionContext(object obj, string function_name)
        {
            _internal = obj;
            this._function_name = function_name;
        }

        public bool IsDefined
        {
            get
            {
                return _function != null ? true : false;
            }
        }

        public Func<PARAM1,RETVAL> define
        {
            set
            {
                _function = value;
            }
        }

        public Func<PARAM1,RETVAL> call
        {
            get
            {
                if (_function != null)
                    return _function;
                else
                {
                    object prototype = _internal.GetPrototype();
                    if (prototype != null)
                        return prototype.function<PARAM1,RETVAL>(_function_name).call;
                }

                throw new MissingMethodException("The specified function has not been defined for this instance");
            }
        }

    }

    public class DynamicFunctionContext<PARAM1,PARAM2,RETVAL>
    {
        object _internal;
        Func<PARAM1, PARAM2, RETVAL> _function;
        string _function_name;

        public DynamicFunctionContext(object obj, string function_name)
        {
            _internal = obj;
            this._function_name = function_name;
        }

        public bool IsDefined
        {
            get
            {
                return _function != null ? true : false;
            }
        }

        public Func<PARAM1, PARAM2, RETVAL> define
        {
            set
            {
                _function = value;
            }
        }

        public Func<PARAM1, PARAM2, RETVAL> call
        {
            get
            {
                if (_function != null)
                    return _function;
                else
                {
                    object prototype = _internal.GetPrototype();
                    if (prototype != null)
                        return prototype.function<PARAM1, PARAM2, RETVAL>(_function_name).call;
                }

                throw new MissingMethodException("The specified function has not been defined for this instance");
            }
        }

    }

    public class DynamicFunctionContext<PARAM1, PARAM2, PARAM3,RETVAL>
    {
        object _internal;
        Func<PARAM1, PARAM2, PARAM3, RETVAL> _function;
        string _function_name;

        public DynamicFunctionContext(object obj, string function_name)
        {
            _internal = obj;
            this._function_name = function_name;
        }

        public bool IsDefined
        {
            get
            {
                return _function != null ? true : false;
            }
        }

        public Func<PARAM1, PARAM2, PARAM3, RETVAL> define
        {
            set
            {
                _function = value;
            }
        }

        public Func<PARAM1, PARAM2, PARAM3, RETVAL> call
        {
            get
            {
                if (_function != null)
                    return _function;
                else
                {
                    object prototype = _internal.GetPrototype();
                    if (prototype != null)
                        return prototype.function<PARAM1, PARAM2, PARAM3, RETVAL>(_function_name).call;
                }

                throw new MissingMethodException("The specified function has not been defined for this instance");
            }
        }

    }

    public class DynamicFunctionContext<PARAM1, PARAM2, PARAM3, PARAM4,RETVAL>
    {
        object _internal;
        Func<PARAM1, PARAM2, PARAM3, PARAM4, RETVAL> _function;
        string _function_name;

        public DynamicFunctionContext(object obj, string function_name)
        {
            _internal = obj;
            this._function_name = function_name;
        }

        public bool IsDefined
        {
            get
            {
                return _function != null ? true : false;
            }
        }

        public Func<PARAM1, PARAM2, PARAM3, PARAM4, RETVAL> define
        {
            set
            {
                _function = value;
            }
        }

        public Func<PARAM1, PARAM2, PARAM3, PARAM4, RETVAL> call
        {
            get
            {
                if (_function != null)
                    return _function;
                else
                {
                    object prototype = _internal.GetPrototype();
                    if (prototype != null)
                        return prototype.function<PARAM1, PARAM2, PARAM3, PARAM4, RETVAL>(_function_name).call;
                }

                throw new MissingMethodException("The specified function has not been defined for this instance");
            }
        }

    }
}
